﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web.Mvc;

namespace ProjectBase.Core
{
    /// <summary>
    ///     Extensions available on every place of the framework.
    /// </summary>
    public static partial class Ext
    {
        #region byte compare
        static readonly BinaryFormatter BinaryFormatter = new BinaryFormatter();

        /// <summary>
        ///     Compares two byte[] arrays if they contain same bytes
        /// </summary>
        /// <param name = "array">if null false is returned</param>
        /// <param name = "toCompare">if null false is returned</param>
        /// <returns>true if both byte arrays contains same bytes</returns>
        public static bool Compare(this byte[] array, byte[] toCompare)
        {
            if (array.Is() && toCompare.Is())
            {
                if (array.Length == toCompare.Length)
                {
                    var i = 0;
                    while ((i < array.Length)
                           && (array[i] == toCompare[i]))
                    {
                        i++;
                    }
                    if (i == array.Length)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        ///     Compares two serializable objects.
        ///     Converts them into byte[] array using BinaryFormatter
        ///     and than compares these byte[] arrays
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "toCompare"></param>
        /// <returns></returns>
        public static bool ByteCompare(this object value, object toCompare)
        {
            using (var msObj = new MemoryStream())
            {
                using (var msToCompare = new MemoryStream())
                {
                    BinaryFormatter.Serialize(msObj, value);
                    BinaryFormatter.Serialize(msToCompare, toCompare);

                    return msObj.ToArray().Compare(msToCompare.ToArray());
                }
            }
        }

        /// <summary>
        ///     Uses the MemoryStream to convert provided value into the byte array
        /// </summary>
        /// <param name = "value"></param>
        /// <returns></returns>
        public static byte[] ToByteArray(this IPersistentObject value)
        {
            return GetByteArray(value);
        }
        /// <summary>
        ///     Universal object serializer. Must be used explictily: ProjectBase.Core.Ext.ToByteArray(...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] ToByteArray<T>(T value)
        {
            return GetByteArray(value);
        }

        /// <summary>
        ///     Uses the MemoryStream to convert provided value into the byte array
        /// </summary>
        /// <param name = "value"></param>
        /// <returns></returns>
        public static byte[] ToByteArray(this IFilter value)
        {
            return GetByteArray(value);
        }

        /// <summary>
        ///     Uses the MemoryStream to convert provided value into the byte array
        /// </summary>
        /// <param name = "controller"></param>
        /// <param name = "value"></param>
        /// <returns></returns>
        public static byte[] ToByteArray(this ControllerContext controller, object value)
        {
            return GetByteArray(value);
        }

        /// <summary>
        ///     Uses the MemoryStream to convert provided value into the byte array.
        ///     If value
        ///     1) is null or
        ///     2) cannot be serialized (SerializationException),
        ///     then new byte[0] is returned
        /// </summary>
        /// <param name = "value"></param>
        /// <returns></returns>
        static byte[] GetByteArray(object value)
        {
            if (value.IsNull())
            {
                return new byte[0];
            }
            using (var ms = new MemoryStream())
            {
                try
                {
                    BinaryFormatter.Serialize(ms, value);
                    return ms.ToArray();
                }
                catch (System.Runtime.Serialization.SerializationException ex)
                {
                    PublishingManager.Publish(null, "Cannot serialize object (e.g. session): {0}".FormatWith(value.ToString()), ex);
                }
                return new byte[0];
            }
        }
        #endregion byte compare
    }
}